package com.moco.launcher;

/*
 * Copyright (C) 2008 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import io.netty.channel.ChannelHandlerContext;

import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import android.app.Activity;
import android.app.ActivityManager;
import android.app.Application;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.res.Configuration;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.util.Log;

import com.moco.launcher.activity.MainActivity;
import com.moco.launcher.activity.PopActivity;
import com.moco.launcher.activity.PowerOffActivity;
import com.moco.launcher.activity.VoiceActivity;
import com.moco.launcher.activity.VolumeActivity;
import com.moco.launcher.adapter.DataAdapter;
import com.moco.launcher.bean.MOCO_CONSTANTS;
import com.moco.launcher.download.MocoDownloadManager;
import com.moco.launcher.fragment.PlayFragment;
import com.moco.launcher.link.LinkManager;
import com.moco.launcher.listener.EventCallback;
import com.moco.launcher.play.MocoPlayerClient;
import com.mradar.sdk.record.Logger;
import com.nostra13.universalimageloader.cache.disc.impl.UnlimitedDiscCache;
import com.nostra13.universalimageloader.cache.disc.naming.Md5FileNameGenerator;
import com.nostra13.universalimageloader.cache.memory.impl.WeakMemoryCache;
import com.nostra13.universalimageloader.core.ImageLoader;
import com.nostra13.universalimageloader.core.ImageLoaderConfiguration;
import com.nostra13.universalimageloader.core.assist.QueueProcessingType;
import com.nostra13.universalimageloader.core.download.BaseImageDownloader;
import com.nostra13.universalimageloader.utils.StorageUtils;
import com.oazon.common.TaskHelper;
import com.oazon.common.util.RequestManager;
import com.oazon.common.util.Utils;
import com.oazon.moco.bean.McServiceMsg;
import com.oazon.moco.bean.Metadata;
import com.oazon.moco.lan.core.http.bean.AVTransportUri;
import com.oazon.moco.lan.core.http.bean.DeleteBean;
import com.oazon.moco.lan.core.http.bean.FavoriteBean;
import com.oazon.moco.lan.core.http.bean.ResponseUriToQueue;
import com.oazon.moco.lan.core.http.bean.UriToQueue;
import com.oazon.moco.link.SaveMediaState;
import com.oazon.moco.link.core.LinkEventController;
import com.oazon.moco.link.core.LinkSDK;
import com.oazon.moco.link.core.source.LinkEventSource;
import com.oazon.moco.playlist.PlayListManage;
import com.oazon.moco.playlist.bean.AbstractMedia;
import com.oazon.moco.playlist.bean.PlayListCurrentMode;
import com.oazon.moco.playlist.db.ServiceMsgDao;
import com.oazon.sonos.bean.GetMetadata;
import com.oazon.sonos.bean.GetMetadataResponse;
import com.oazon.sonos.core.SonosControler;
import com.oazon.sonos.listener.SonosListener;
import com.oazon.sonos.util.SonosUtil;

public class LauncherApplication extends Application {
	private static final String TAG = "LauncherApplication";
	private static boolean sIsScreenLarge;
	private static float sScreenDensity;
	private static int sLongPressTimeout = 300;
	private static final String sSharedPreferencesKey = "com.example.launcher.prefs";
	private Activity mAt = null;
	private ActivityManager activityManager;
	private String runningActivity;

	private Map<String, Object> tempObject = new HashMap<String, Object>();

	private PlayFragment mPf = null;

	private MainActivity mMainActivity = null;

	private Handler toPlayItemHandler;

	private boolean isShowVoiceFragment = false;

	private boolean isOpenSwitchSongGesture = false;

	private static LauncherApplication instance;

	// 添加是否开启手势切换的全局变量
	public void setOpenSwitchSongGesture(boolean value) {
		isOpenSwitchSongGesture = value;
	}

	public boolean getOpenSwitchSongGesture() {
		return isOpenSwitchSongGesture;
	}

	public Object getTempObject(String key) {
		return tempObject.get(key);
	}

	public void setTempObject(String key, Object value) {
		tempObject.put(key, value);
	}

	public boolean isShowVoiceFragment() {
		return isShowVoiceFragment;
	}

	public void setShowVoiceFragment(boolean isShowVoiceFragment) {
		this.isShowVoiceFragment = isShowVoiceFragment;
	}

	public static LauncherApplication getInstance() {
		return instance;
	}

	@Override
	public void onCreate() {
		super.onCreate();

		new CatchHandler(this);
		PlayListManage.init(getApplicationContext());
		Log.d(TAG, "onCreate");
		// initImageLoader(getApplicationContext());
		// set sIsScreenXLarge and sScreenDensity *before* creating icon cache
		sIsScreenLarge = getResources().getBoolean(R.bool.is_large_screen);
		sScreenDensity = getResources().getDisplayMetrics().density;

		instance = this;

		MocoDownloadManager.getInstance().init(this);
		RequestManager.init(this);
		MocoPlayerClient.getInstance().init(this);
		MocoPlayerClient.getInstance().startPlayService();
		LinkManager.getInstance().init(this);

		com.oazon.common.Logger.restoreDebugState(this);

		// 为了事件模块的回调
		LinkManager.getInstance().registerCallback(new EventCallback() {

			@Override
			public void speechStart() {
				Log.i(TAG, "mAt==" + mAt + "isShowVoiceFragment==="
						+ isShowVoiceFragment);
				if (mAt == null || isShowVoiceFragment) {

					Log.i(TAG, "语音开始");
					return;
				}
				Intent intent = new Intent(mAt, VoiceActivity.class);
				intent.putExtra("fragment_type", "voice");
				mAt.startActivity(intent);
			}

			@Override
			public void showScreenProtectFlagment() {
				if (mAt == null) {
					return;
				}

				activityManager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
				runningActivity = activityManager.getRunningTasks(1).get(0).topActivity
						.getClassName();
				runningActivity = runningActivity.substring(runningActivity
						.lastIndexOf(".") + 1);

				Intent intent = new Intent(mAt, PowerOffActivity.class);

				mAt.startActivity(intent);
			}

			@Override
			public void finishScreenProtectActivity() {
				if (mAt == null) {
					return;
				}
				Intent intent = new Intent(mAt, MainActivity.class);
				intent.putExtra("playState", SaveMediaState.getInstance()
						.getTransportState().toString());
				intent.putExtra("activity", runningActivity);
				mAt.startActivity(intent);

			}

			@Override
			public void speachStop() {
				/*
				 * if(mAt == null){ return; } Intent intent = new Intent(mAt,
				 * VoiceActivity.class); intent.putExtra("fragment_type",
				 * "voice"); intent.putExtra("isExit", true);
				 * mAt.startActivity(intent);
				 */
			}

			@Override
			public void adr() {
				if (mAt == null) {
					return;
				}
				Intent intent = new Intent(mAt, PopActivity.class);
				intent.putExtra("fragment_type", "adr");
				mAt.startActivity(intent);
			}

			@Override
			public void playNext() {
				MocoPlayerClient.getInstance().playNext();
			}

			@Override
			public void playPrev() {
				MocoPlayerClient.getInstance().playPrev();
			}

			@Override
			public void playPause(final boolean notifyAll) {
				if (mAt == null) {
					return;
				}
				mAt.runOnUiThread(new Runnable() {

					@Override
					public void run() {
						if (MocoPlayerClient.getInstance().isPlaying()) {
							mPf.showPauseState();
							MocoPlayerClient.getInstance().iPause(notifyAll,
									false);
						}
					}
				});
			}

			@Override
			public void playStart(final boolean notifyAll) {
				if (mAt == null) {
					return;
				}
				mAt.runOnUiThread(new Runnable() {

					@Override
					public void run() {
						mPf.showPlayState();
						MocoPlayerClient.getInstance().iStart(notifyAll);
					}
				});

			}

			@Override
			public void playStop() {
				MocoPlayerClient.getInstance().stop();
			}

			@Override
			public void volumeUp() {
				if (mAt == null) {
					return;
				}
				mAt.runOnUiThread(new Runnable() {

					@Override
					public void run() {
						Intent intent = new Intent(mAt, VolumeActivity.class);
						intent.putExtra("fragment_type", "volume");
						mAt.startActivity(intent);
					}
				});

			}

			@Override
			public void volumDown() {
				if (mAt == null) {
					return;
				}
				mAt.runOnUiThread(new Runnable() {

					@Override
					public void run() {
						Intent intent = new Intent(mAt, VolumeActivity.class);
						intent.putExtra("fragment_type", "volume");
						mAt.startActivity(intent);
					}
				});

			}

			@Override
			public void batteryChange(int percent) {
				if (mAt == null) {
					return;
				}
				Intent intent = new Intent();
				intent.setAction("com.moco.battery.change");
				intent.putExtra("percent", percent);
				mAt.sendBroadcast(intent);
			}

			@Override
			public void seekTo(long pos) {
				MocoPlayerClient.getInstance().seekTo(pos);
			}

			@Override
			public void setVolume(int volume) {
				if (mAt == null) {
					return;
				}
				Intent intent = new Intent(mAt, VolumeActivity.class);
				intent.putExtra("fragment_type", "volume");
				intent.putExtra("volume", volume);
				mAt.startActivity(intent);
			}

			// vicent.1
			@Override
			public void favorite(FavoriteBean favoriteBean,
					ChannelHandlerContext ctx) {
				if (mPf != null) {
					Logger.i(TAG, "here is the launcherApp cn-------------");
					// mPf.loveMetadata(favoriteBean, ctx);
					mPf.loveCurrentMetadata(true, ctx);

				}
			}

			@Override
			public void delete(DeleteBean deleteBean, ChannelHandlerContext ctx) {
				if (mPf != null) {
					mPf.deleteCurrentMetadata(true);
				}
			}

			@Override
			public void playMode(String playMode) {
				if (mAt == null) {
					return;
				}
				Intent intent = new Intent();
				intent.setAction("com.moco.play.playmode");
				intent.putExtra("playMode", playMode);
				mAt.sendBroadcast(intent);
			}

			@Override
			public ResponseUriToQueue addUriToQueue(String uuid,
					UriToQueue uriToQueue, LinkEventSource linkEventSource) {

				PlayListManage.getInstance().toQueue();

				ResponseUriToQueue response = new ResponseUriToQueue();

				int index = uriToQueue.getInstances().get(0)
						.getDesiredFirstTrackNumberEnqueued();

				String objectClass = uriToQueue.getInstances().get(0)
						.getEnqueuedURIMetaData().getObjectClass();

				if ("object.item.audioItem.musicTrack".equals(objectClass)) {

					List<Metadata> metadatas = new ArrayList<Metadata>();

					for (int i = 0; i < uriToQueue.getInstances().size(); i++) {
						metadatas.add(DataAdapter.dateAdapator(uriToQueue
								.getInstances().get(i)));
					}

					if (index > 0) {
						mMainActivity.addMusicList(index, metadatas, false);
						response.setFirstTrackNumberEnqueued(PlayListManage.getInstance().getReadIndex());
					} else {
						index = PlayListManage.getInstance().size();
						mMainActivity.addMusicList(index, metadatas, false);
						response.setFirstTrackNumberEnqueued(PlayListManage.getInstance().size() - 1);
					}

					response.setNumTracksAdded(uriToQueue.getInstances().size());
					response.setNewQueueLength(PlayListManage.getInstance()
							.size());

				} else if ("object.container.playlistContainer"
						.equals(objectClass)) {
					response = null;
					if(index<=0){
						index = PlayListManage.getInstance().size();
					}
					requestContainer(uriToQueue, linkEventSource, index);
				}

				return response;
			}

			@Override
			public void avTransport(AVTransportUri avTransportUri) {
				AVTransportUri.Instance instance = avTransportUri
						.getInstances().get(0);
				if (instance == null) {
					return;
				}
				String curUri = instance.getCurrentURI();
				String playListMode = "";
				if (curUri != null) {
					playListMode = curUri.split("[:]")[0];
				}

				if ("x-o2api-radio".equals(playListMode)) {
					PlayListManage.getInstance().toSmartRadio(null);
					requestRadio(instance);
				} else if ("x-o2-queue".equals(playListMode)) {
					if (PlayListManage.getInstance().getSaveCurrentMode() == PlayListCurrentMode.SMART_RADIO) {
						PlayListManage.getInstance().toQueue();
						mPf.setCurrentItem();
					}
				}
			}

			@Override
			public void toPlayItem(int parseInt) {
				toPlayItemHandler.sendEmptyMessageDelayed(parseInt, 1000);
			}

			@Override
			public void serviceAdded(McServiceMsg msg, String uuid) {
				mMainActivity.onServiceAdded(msg, uuid);
			}

			@Override
			public void serviceDelete(String serviceName, String uuid,ChannelHandlerContext ctx) {
				mMainActivity.onServiceDelete(serviceName, uuid,ctx);
			}
		});
		SharedPreferences mshPreferences = getApplicationContext()
				.getSharedPreferences(Utils.CONFIG_FILE, MODE_PRIVATE);
		Boolean temp = mshPreferences.getBoolean("gesture_value", false);
		Log.i(TAG, "gesture_value==" + temp);
		setOpenSwitchSongGesture(temp);

		TaskHelper.exec(new Runnable() {

			@Override
			public void run() {
				ServiceMsgDao.getInstance(instance);

			}
		});
	}

	/**
	 * 根据MC端的添加歌单到队列，做网络请求并添加到播放队列中
	 * 
	 * @param uriToQueue
	 * @param linkEventSource
	 * @param index
	 */
	private void requestContainer(UriToQueue uriToQueue,
			final LinkEventSource linkEventSource, final int index) {

		final GetMetadata parameters = SonosUtil.fillgetMetadata(//
				uriToQueue.getInstances().get(0).getEnqueuedItemID()//
				, MOCO_CONSTANTS.INDEX//
				, MOCO_CONSTANTS.QUEUE_COUNT//
				, MOCO_CONSTANTS.RECURSIVE//
				, uriToQueue.getInstances().get(0).getEnqueuedServiceID());

		SonosControler.getInstance(
				this.getApplicationContext(),
				ServiceMsgDao.getInstance(mMainActivity)
						.getServiceMsgByProvider(parameters.getProvider()))
				.getMetadata(mMainActivity, parameters, new SonosListener() {

					@Override
					public void onResponse(Object response) {
						if (response == null) {
							return;
						}
						GetMetadataResponse<AbstractMedia> metadataResult = (GetMetadataResponse<AbstractMedia>) response;

						int lastItemCount = PlayListManage.getInstance().size() - index;
						mMainActivity.addMusicList(index, DataAdapter
								.paseMetadatas(metadataResult
										.getGetMetadataResult()
										.getMediaCollectionOrMediaMetadata(),
										null, parameters.getProvider()), false);

						ResponseUriToQueue responseUriToQueue = new ResponseUriToQueue();
						responseUriToQueue
								.setFirstTrackNumberEnqueued(PlayListManage.getInstance().size()-lastItemCount-metadataResult.getGetMetadataResult().getMediaCollectionOrMediaMetadata().size());
						responseUriToQueue.setNewQueueLength(PlayListManage
								.getInstance().size());
						responseUriToQueue.setNumTracksAdded(metadataResult
								.getGetMetadataResult()
								.getMediaCollectionOrMediaMetadata().size());

						LinkManager.getInstance().addUriToQueueResponse(
								linkEventSource, responseUriToQueue);

					}

					@Override
					public void onError(int err, String msg) {
						// TODO Auto-generated method stub

					}
				});
	}

	/**
	 * 
	 * @param instance
	 * @param curUri
	 */
	private void requestRadio(AVTransportUri.Instance instance) {

		final GetMetadata parameters = SonosUtil.fillgetMetadata(//
				instance.getCurrentItemID()//
				, MOCO_CONSTANTS.INDEX//
				, MOCO_CONSTANTS.RADIO_COUNT//
				, MOCO_CONSTANTS.RECURSIVE//
				, instance.getCurrentServiceID());

		SonosControler.getInstance(
				this.getApplicationContext(),
				ServiceMsgDao.getInstance(mMainActivity)
						.getServiceMsgByProvider(parameters.getProvider()))
				.getMetadata(mMainActivity, parameters, new SonosListener() {

					@Override
					public void onResponse(Object response) {
						try {
							GetMetadataResponse<AbstractMedia> result = (GetMetadataResponse<AbstractMedia>) response;
							if (result == null)
								return;

							List<Metadata> metadatas = DataAdapter
									.paseMetadatas(
											result.getGetMetadataResult()
													.getMediaCollectionOrMediaMetadata(),
											parameters.getId(), parameters
													.getProvider());
							mPf.addSmartRadioAndPlay(metadatas, parameters);
						} catch (Exception e) {
							onError(0, e.getMessage());
						}

					}

					@Override
					public void onError(int err, String msg) {
					}
				});
	}

	/**
	 * There's no guarantee that this function is ever called.
	 */
	@Override
	public void onTerminate() {
		LinkManager.getInstance().destrory();
		super.onTerminate();
	}

	public static String getSharedPreferencesKey() {
		return sSharedPreferencesKey;
	}

	public static boolean isScreenLarge() {
		return sIsScreenLarge;
	}

	public static boolean isScreenLandscape(Context context) {
		return context.getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE;
	}

	public static float getScreenDensity() {
		return sScreenDensity;
	}

	public static int getLongPressTimeout() {
		return sLongPressTimeout;
	}

	/** 鍒濆鍖朓mageLoader */
	public static void initImageLoader(Context context) {
		String filePath = Environment.getExternalStorageDirectory()
				+ "/Android/data/" + context.getPackageName() + "/cache/";

		File cacheDir = StorageUtils.getOwnCacheDirectory(context, filePath);// 鑾峰彇鍒扮紦瀛樼殑鐩綍鍦板潃
		Log.d("cacheDir", cacheDir.getPath());
		// 鍒涘缓閰嶇疆ImageLoader(鎵�湁鐨勯�椤归兘鏄彲閫夌殑,鍙娇鐢ㄩ偅浜涗綘鐪熺殑鎯冲畾鍒�锛岃繖涓彲浠ヨ瀹氬湪APPLACATION閲岄潰锛岃缃负鍏ㄥ眬鐨勯厤缃弬鏁�
		ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(
				context)
				// .memoryCacheExtraOptions(480, 800) // max width, max
				// height锛屽嵆淇濆瓨鐨勬瘡涓紦瀛樻枃浠剁殑鏈�ぇ闀垮
				// .discCacheExtraOptions(480, 800, CompressFormat.JPEG,
				// 75, null) // Can slow ImageLoader, use it carefully
				// (Better don't use it)璁剧疆缂撳瓨鐨勮缁嗕俊鎭紝鏈�ソ涓嶈璁剧疆杩欎釜
				.threadPoolSize(3)
				// 绾跨▼姹犲唴鍔犺浇鐨勬暟閲� .threadPriority(Thread.NORM_PRIORITY - 2)
				.denyCacheImageMultipleSizesInMemory()
				.memoryCache(new WeakMemoryCache())
				// .memoryCache(new UsingFreqLimitedMemoryCache(2 * 1024
				// * 1024)) // You can pass your own memory cache
				// implementation浣犲彲浠ラ�杩囪嚜宸辩殑鍐呭瓨缂撳瓨瀹炵幇
				.memoryCacheSize(2 * 1024 * 1024)
				// /.discCacheSize(50 * 1024 * 1024)
				.discCacheFileNameGenerator(new Md5FileNameGenerator())// 灏嗕繚瀛樼殑鏃跺�鐨刄RI鍚嶇О鐢∕D5
																		// 鍔犲瘑
				// .discCacheFileNameGenerator(new
				// HashCodeFileNameGenerator())//灏嗕繚瀛樼殑鏃跺�鐨刄RI鍚嶇О鐢℉ASHCODE鍔犲瘑
				.tasksProcessingOrder(QueueProcessingType.LIFO)
				// .discCacheFileCount(100) //缂撳瓨鐨凢ile鏁伴噺
				.discCache(new UnlimitedDiscCache(cacheDir))// 鑷畾涔夌紦瀛樿矾寰�
															// .defaultDisplayImageOptions(DisplayImageOptions.createSimple())
				.imageDownloader(
						new BaseImageDownloader(context, 5 * 1000, 30 * 1000)) // connectTimeout
																				// (5
																				// s),
				// readTimeout(30)// 瓒呮椂鏃堕棿
				.writeDebugLogs() // Remove for release app
				.build();
		// Initialize ImageLoader with configuration.
		ImageLoader.getInstance().init(config);// 鍏ㄥ眬鍒濆鍖栨閰嶇疆
	}

	public synchronized void resetStartTime() {
		LinkSDK.getInstance().hasAction(LinkEventController.uiSource);
	}

	public void registerActivty(Activity at) {
		mAt = at;
		if (at instanceof MainActivity) {
			mMainActivity = (MainActivity) at;
		}

	}

	public void registerPlayFragment(PlayFragment pf) {
		mPf = pf;
		toPlayItemHandler = new Handler(pf.getActivity().getMainLooper()) {
			public void handleMessage(Message msg) {
				mPf.playItem(msg.what);
			};
		};
	}

	public PlayFragment getPlayFragment() {
		return mPf;
	}

}
